package net.borlis.errors.annotations;

import net.borlis.errors.providers.common.IServerExceptionProcessor;
import net.borlis.errors.providers.implementation.filebase.LocaleFileErrors;

import javax.inject.Inject;
import javax.interceptor.AroundInvoke;
import javax.interceptor.Interceptor;
import javax.interceptor.InvocationContext;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author alex@borlis.net
 */
@Interceptor
@ServerExceptionRegister(expected = {})
public class ServerExceptionInterceptor {

    @Inject
    private Logger logger;

    @Inject
    @LocaleFileErrors
    private IServerExceptionProcessor exceptionProcessor;

    @AroundInvoke
    public Object checkRunningCode(InvocationContext ctx) throws Exception { //NOPMD
        // there is a conflict between SONAR/CDI
        final ServerExceptionRegister annotation = ctx.getMethod().getAnnotation(ServerExceptionRegister.class);
        final Class<? extends Throwable>[] expectedItems = annotation.expected();
        if (expectedItems.length == 0) {
            throw new IllegalStateException("annotation over " + ctx.getMethod().getName() +
                    " in " +  ctx.getMethod().getDeclaringClass().getName() +
                    " must have it least one declaration of an exception type.");
        }
        // -=-=-=-
        try {
            // -=-=-=-=-=-
            logger.log(Level.FINE, "The class name: " + ctx.getMethod().getDeclaringClass().getName());
            logger.log(Level.FINE, "The method name: " + ctx.getMethod().getName());
            logger.log(Level.FINE, "The content data: " + ctx.getContextData().toString());
            // -=-=-=-=-=-
            return ctx.proceed();
            // -=-=-=-=-=-
        } catch (Exception ce) {
            for (Class<? extends Throwable> expectedItem : expectedItems) {
                if (expectedItem.equals(ce.getClass())) {
                    logger.log(Level.SEVERE, annotation.logMessage(), ce);
                    throw exceptionProcessor.newServerException(annotation.code(), ce);
                }
            }
            logger.log(Level.SEVERE, annotation.logMessage(), ce);
            throw ce;
        }
    }

}
